home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / VObject.C < prev    next >
C/C++ Source or Header  |  1992-08-26  |  20KB  |  991 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "VObject.h"
  6.  
  7. #include "Class.h"
  8. #include "Menu.h"
  9. #include "Window.h"
  10. #include "WindowSystem.h"
  11. #include "String.h"
  12. #include "PrintManager.h"
  13. #include "ProgEnv.h"
  14. #include "OrdColl.h"
  15. #include "View.h"
  16. #include "Look.h"
  17. #include "Math.h"
  18.  
  19. Point gBorder(4, 2);
  20.  
  21. const int cAutoSize = -1;
  22.  
  23. bool testopen= FALSE;
  24.  
  25. //---- VObject -----------------------------------------------------------------
  26.  
  27. NewAbstractMetaImpl(VObject,EvtHandler, (TP(container), T(contentRect)));
  28.  
  29. VObject::VObject(Rectangle r, int id)
  30. {
  31.     SetId(id);
  32.     contentRect= r;
  33.     container= 0;
  34.     SetFlag(eVObjDefault);
  35.     if (!testopen)
  36.     SetFlag(eVObjOpen);
  37. }
  38.  
  39. VObject::VObject(int id)
  40. {
  41.     SetId(id);
  42.     contentRect= gRect0;
  43.     container= 0;
  44.     SetFlag(eVObjDefault);
  45.     if (!testopen)
  46.     SetFlag(eVObjOpen);
  47. }
  48.  
  49. void VObject::FreeAll()
  50. {
  51.     Iter next(MakeIterator());
  52.     Object *op;
  53.  
  54.     while (op= next())
  55.     op->FreeAll();
  56. }
  57.  
  58. VObject::~VObject()
  59. {
  60.     VObject *tmp= container;
  61.     container= 0;
  62.     if (tmp)
  63.     tmp->Remove(this);
  64. }
  65.  
  66. int VObject::Size()
  67. {
  68.     return 0;
  69. }
  70.  
  71. VObject *VObject::At(int)
  72. {
  73.     AbstractMethod("At");
  74.     return 0;
  75. }
  76.  
  77. VObject *VObject::SetAt(int, VObject*)
  78. {
  79.     AbstractMethod("SetAt");
  80.     return 0;
  81. }
  82.  
  83. Iterator *VObject::MakeIterator(bool)
  84. {
  85.     return new Iterator0;
  86. }
  87.  
  88. void VObject::Add(VObject*)
  89. {
  90.     AbstractMethod("Add");
  91. }
  92.  
  93. VObject *VObject::Remove(VObject*)
  94. {
  95.     AbstractMethod("Remove");
  96.     return 0;
  97. }
  98.  
  99. void VObject::RemoveFromContainer()
  100. {
  101.     if (container) {
  102.     VObject *tmp= container;
  103.     container= 0;
  104.     tmp->Remove(this);
  105.     }
  106. }
  107.  
  108. void VObject::SendDown(int id, int part, void *val)
  109. {
  110.     Iter next(MakeIterator());
  111.     VObject *vop;
  112.  
  113.     while (vop= (VObject*) next())
  114.     vop->SendDown(id, part, val);
  115. }
  116.  
  117. void VObject::CollectParts(Collection* col)
  118. {
  119.     Iter next(MakeIterator());
  120.     Object *op;
  121.  
  122.     while (op= next())
  123.     col->Add(op);
  124. }
  125.  
  126. //---- state -------------------------------------------------------------------
  127.  
  128. void VObject::Open(bool mode)
  129. {
  130.     SetFlag(eVObjOpen, mode);
  131.     if (Size() > 0) {
  132.     Iter next(MakeIterator());
  133.     VObject *vop;
  134.     
  135.     if (testopen) {
  136.         while (vop= (VObject*) next())
  137.         if (vop->IsOpen() != mode)
  138.             vop->Open(mode);
  139.     } else {
  140.         while (vop= (VObject*) next())
  141.         vop->Open(mode);
  142.     }
  143.     }
  144.     if (TestFlag(eVObjKbdFocus)) {
  145.     Window *w= GetWindow();
  146.     if (w) {
  147.         Manager *m= (Manager*)w->GetNextHandler();
  148.         if (m)  {
  149.         if (mode) {
  150.             if (m->GetFirstHandler() == 0) {
  151.             m->SetFirstHandler(this);
  152.             }
  153.         } else {
  154.             if (m->GetFirstHandler() == this) {
  155.             m->SetFirstHandler(0);
  156.             }
  157.         }
  158.         }
  159.     }
  160.     }
  161. }
  162.  
  163. bool VObject::IsOpen()
  164. {
  165.     return TestFlag(eVObjOpen);
  166. }
  167.  
  168. void VObject::Enable(bool b, bool redraw)
  169. {
  170.     if ((TestFlag(eVObjEnabled) != 0) != (b != 0)) {
  171.     SetFlag(eVObjEnabled, b);
  172.     if (redraw)
  173.         ForceRedraw();
  174.     if (Size() > 0) {
  175.         Iter next(MakeIterator());
  176.         VObject *vop;
  177.         while (vop= (VObject*) next())
  178.         vop->Enable(b, FALSE);
  179.     }
  180.     }
  181. }
  182.  
  183. void VObject::Highlight(HighlightState hst)
  184. {
  185.     bool b= (hst == On);
  186.     if (TestFlag(eVObjHighlight) != b) {
  187.     SetFlag(eVObjHighlight, b);
  188.     ForceRedraw();
  189.     }
  190. }
  191.  
  192. //---- container ---------------------------------------------------------------
  193.  
  194. void VObject::SetContainer(VObject *v)
  195. {
  196.     container= v;
  197. }
  198.  
  199. void VObject::ClearContainer(VObject *v)
  200. {
  201.     if (container && container == v)
  202.     container= 0;
  203. }
  204.  
  205. VObject *VObject::FindContainerOfClass(Class *cla)
  206. {
  207.     register VObject *vp;
  208.     
  209.     if (cla == Meta(Window))
  210.     vp= this;
  211.     else
  212.     vp= GetContainer();
  213.     
  214.     for (; vp; vp= vp->GetContainer()) {
  215.     if (vp->IsA()->isKindOf(cla))
  216.         return vp;
  217.     }
  218.     return 0;
  219. }
  220.  
  221. Point VObject::ContainerPoint(Point p)
  222. {
  223.     return p;
  224. }
  225.  
  226. Point VObject::GetPortPoint(Point p)
  227. {
  228.     p= ContainerPoint(p);
  229.     if (GetContainer())
  230.     return GetContainer()->GetPortPoint(p);
  231.     return p;
  232. }
  233.  
  234. Window *VObject::GetWindow()
  235. {
  236.     return (Window*) FindContainerOfClass(Meta(Window));
  237. }
  238.  
  239. View *VObject::GetView()
  240. {
  241.     return (View*) FindContainerOfClass(Meta(View));
  242. }
  243.  
  244. Clipper *VObject::Getclipper()
  245. {
  246.     return (Clipper*) FindContainerOfClass(Meta(Clipper));
  247. }
  248.  
  249. /*
  250. void VObject::AddToClipper(Clipper *clipper)
  251. {
  252.     VObject::SetContainer(clipper);
  253.     CalcExtent();
  254.     SetOrigin(gPoint0);
  255. }
  256. */
  257.  
  258. Rectangle VObject::GetViewedRect()
  259. {
  260.     return contentRect;
  261. }
  262.  
  263. void VObject::Focus()
  264. {
  265.     if (GetContainer())
  266.     GetContainer()->Focus();
  267. }
  268.  
  269. //---- tree walking ------------------------------------------------------------
  270.  
  271. VObject *VObject::Detect(BoolFun find, void *arg)
  272. {
  273.     if (Size() > 0) {
  274.     VObject *g1, *g2;
  275.     Iter next(MakeIterator());
  276.  
  277.     while (g1= (VObject*) next())
  278.         if (g2= g1->Detect(find, arg))
  279.         return g2;
  280.     }
  281.     if (find(this, this, arg))
  282.     return this;
  283.     return 0;
  284. }
  285.  
  286. static bool Comp1(Object*, Object *op, void *v)
  287. {
  288.     return (bool) (((VObject*)(op))->GetId() == (int)v);
  289. }
  290.  
  291. static bool Comp2(Object*, Object *op, void *v)
  292. {
  293.     VObject *vop= (VObject*) op;
  294.     Point p= *((Point*)v);
  295.     return vop->ContainsPoint(p - vop->ContainerPoint(gPoint0));
  296.     //return vop->ContainsPoint(p);
  297. }
  298.  
  299. static bool Comp3(Object*, Object *op, void *v)
  300. {
  301.     return op->IsEqual((VObject*)v);
  302. }
  303.  
  304. static bool Comp4(Object*, Object *op, void *v)
  305. {
  306.     return op == (VObject*)v;
  307. }
  308.  
  309. VObject *VObject::FindItem(int id)
  310. {
  311.     if (id != cIdNone)
  312.     return Detect(Comp1, (void*) id);
  313.     return 0;
  314. }
  315.  
  316. VObject *VObject::FindItem(Point p)
  317. {
  318.     return Detect(Comp2, &p);
  319. }
  320.  
  321. VObject *VObject::FindItem(VObject *g)
  322. {
  323.     return Detect(Comp3, g);
  324. }
  325.  
  326. VObject *VObject::FindItemPtr(VObject *g)
  327. {
  328.     return Detect(Comp4, g);
  329. }
  330.  
  331. //---- layout ------------------------------------------------------------------
  332.  
  333. Metric VObject::GetMinSize()
  334. {
  335.     if (Size() > 0) {
  336.     Metric m;
  337.     Iter next(MakeIterator());
  338.     VObject *dip;
  339.     
  340.     while (dip= (VObject*) next())
  341.         m.Merge(dip->GetMinSize());
  342.     return m;
  343.     }
  344.     return Metric(contentRect.extent);
  345. }
  346.  
  347. void VObject::CalcExtent()
  348. {
  349.     SetExtent(GetMinSize().Extent());
  350. }
  351.  
  352. int VObject::Base()
  353. {
  354.     return GetMinSize().base;
  355. }
  356.  
  357. void VObject::SetOrigin(Point origin)
  358. {
  359.     if (contentRect.origin != origin) {
  360.     contentRect.origin= origin;
  361.     if (TestFlag(eVObjLayoutCntl)) 
  362.         Control(GetId(), cPartOriginChanged, this);
  363.     Object::Send(GetId(), cPartOriginChanged, &origin);
  364.     }
  365. }
  366.  
  367. void VObject::SetExtent(Point extent)
  368. {
  369.     if (contentRect.extent != extent) {
  370.     contentRect.extent= extent;
  371.     if (TestFlag(eVObjLayoutCntl)) 
  372.         Control(GetId(), cPartExtentChanged, this);
  373.        //  Object::Send(GetId(), cPartExtentChanged, this);
  374.     Object::Send(GetId(), cPartExtentChanged, &extent);
  375.     }
  376. }
  377.  
  378. void VObject::ExtentChanged(VObject*)
  379. {
  380.     if (GetContainer())
  381.     GetContainer()->ExtentChanged(this);
  382.     //SetExtent(Max(GetMinSize().Extent(), GetExtent()));
  383. }
  384.  
  385. void VObject::SetContentRect(Rectangle r, bool redraw)
  386. {
  387.     if (!redraw && contentRect == r)
  388.     return;
  389.     if (redraw)
  390.     ForceRedraw();
  391.     if (contentRect.extent != r.extent)
  392.     SetExtent(r.extent);
  393.     SetOrigin(r.origin);
  394.     if (redraw)
  395.     ForceRedraw();
  396. }
  397.  
  398. void VObject::Align(Point at, Metric m, VObjAlign a)
  399. {
  400.     switch (a & eVObjH) {
  401.     case eVObjHLeft:
  402.     break;
  403.     case eVObjHCenter:
  404.     at.x+= (m.Width() - Width())/2;
  405.     break;
  406.     case eVObjHRight:
  407.     at.x+= m.Width() - Width();
  408.     break;
  409.     }
  410.     switch (a & eVObjV) {
  411.     case eVObjVBase:
  412.     at.y+= m.Base() - Base();
  413.     break;
  414.     case eVObjVCenter:
  415.     at.y+= (m.Height() - Height())/2;
  416.     break;
  417.     case eVObjVBottom:
  418.     at.y+= m.Height() - Height();
  419.     break;
  420.     }
  421.     SetOrigin(at);
  422. }
  423.  
  424. void VObject::Move(Point delta, bool redraw)
  425. {
  426.     if (delta == gPoint0)
  427.     return;
  428.     if (redraw)
  429.     ForceRedraw();
  430.     SetOrigin(GetOrigin()+delta);
  431.     if (redraw) {
  432.     ForceRedraw();
  433.     Changed();
  434.     }
  435. }
  436.  
  437. //---- resizing ----------------------------------------------------------------
  438.  
  439. Command *VObject::GetMover()
  440. {
  441.     VObject *v= GetView();
  442.     if (v)
  443.     return new VObjectMover(this, v->contentRect);
  444.     return new VObjectMover(this);
  445. }
  446.  
  447. Command *VObject::GetStretcher()
  448. {
  449.     VObject *v= GetView();
  450.     if (v)
  451.     return new VObjectStretcher(this, v->contentRect);
  452.     return new VObjectStretcher(this);
  453. }
  454.  
  455. bool VObject::ContainsPoint(Point p)
  456. {
  457.     return contentRect.ContainsPoint(p);
  458. }
  459.  
  460. //---- drawing -----------------------------------------------------------------
  461.  
  462. void VObject::DrawAll(Rectangle r, bool highlight)
  463. {
  464.     if (IsOpen() && r.Clip(contentRect))
  465.     DrawInner(r, (bool) (highlight || TestFlag(eVObjHighlight)));
  466. }
  467.  
  468. void VObject::DrawInner(Rectangle r, bool highlight)
  469. {
  470.     if (!GrHasColor())
  471.     Draw(r);
  472.     if (highlight && ! gPrinting)
  473.     DrawHighlight(r);
  474.     if (GrHasColor())
  475.     Draw(r);
  476. }
  477.  
  478. void VObject::Draw(Rectangle r)
  479. {
  480.     if (Size() > 0) {
  481.     Iter next(MakeIterator());
  482.     VObject *vop;
  483.     
  484.     while (vop= (VObject*) next())
  485.         vop->DrawAll(r, FALSE);
  486.     }
  487. }
  488.  
  489. void VObject::DrawHighlight(Rectangle)
  490. {
  491.     gLook->DrawHighlight(contentRect);
  492. }
  493.  
  494. void VObject::Outline2(Point p1, Point p2)
  495. {
  496.     GrStrokeRect(NormRect(p1, p2));
  497. }
  498.  
  499. void VObject::OutlineRect(Rectangle r)
  500. {
  501.     Outline2(r.NW(), r.SE());
  502. }
  503.  
  504. void VObject::Outline(Point delta)
  505. {
  506.     OutlineRect(contentRect+delta);
  507. }
  508.  
  509. void VObject::RevealRect(Rectangle r, Point minToSee)
  510. {
  511.     if (GetContainer())
  512.     GetContainer()->RevealRect(r, minToSee);
  513. }
  514.  
  515. void VObject::RevealAlign(Rectangle r, VObjAlign al)
  516. {
  517.     if (GetContainer())
  518.     GetContainer()->RevealAlign(r, al);
  519. }
  520.  
  521. void VObject::Scroll(int mode, Point scroll, bool redraw)
  522. {
  523.     if (GetContainer())
  524.     GetContainer()->Scroll(mode, scroll, redraw);
  525. }
  526.  
  527. //---- invalidation and focusing -----------------------------------------------
  528.  
  529. void VObject::InvalidateRect(Rectangle r)
  530. {
  531.     if (r.Clip(contentRect) && IsOpen() && GetContainer())
  532.     GetContainer()->InvalidateViewRect(r);
  533. }
  534.  
  535. void VObject::InvalidateViewRect(Rectangle r)
  536. {
  537.     r.origin= ContainerPoint(r.origin);
  538.     InvalidateRect(r);
  539. }
  540.  
  541. void VObject::ForceRedraw()
  542.     InvalidateRect(contentRect);
  543. }
  544.  
  545. void VObject::UpdateEvent()
  546. {
  547.     gWindowSystem->Update();
  548. }
  549.  
  550. GrCursor VObject::GetCursor(Point lp)
  551. {
  552.     if (GetContainer())
  553.     return GetContainer()->GetCursor(ContainerPoint(lp));
  554.     return eCrsBoldArrow;
  555. }
  556.  
  557. //---- input/output ------------------------------------------------------------
  558.  
  559. OStream& VObject::PrintOn(OStream &s)
  560. {
  561.     EvtHandler::PrintOn(s);
  562.     return s << contentRect SP;
  563. }
  564.  
  565. IStream& VObject::ReadFrom(IStream &s)
  566. {
  567.     EvtHandler::ReadFrom(s);
  568.     s >> contentRect;
  569.     container= 0;
  570.     return s;
  571. }
  572.  
  573. //---- input handling ----------------------------------------------------------
  574.  
  575. EvtHandler *VObject::GetNextHandler()
  576. {
  577.     return GetContainer();
  578. }
  579.  
  580. void VObject::DoTrackMouse(TrackPhase atp, Point)
  581. {
  582.     if (Enabled()) {
  583.     switch (atp) {
  584.     case eTrackPress:
  585.         Highlight(On);
  586.         break;
  587.     case eTrackRelease:
  588.         Control(GetId(), cPartToggle, (void*) 1);
  589.     case eTrackExit:
  590.         Highlight(Off);
  591.         break;
  592.     default:
  593.         break;
  594.     }
  595.     }
  596. }
  597.  
  598. void VObject::ReadEvent(Token &t, int timeout, bool overread)
  599. {
  600.     if (GetContainer())
  601.     GetContainer()->ReadEvent(t, timeout, overread);
  602. }
  603.  
  604. Command *VObject::Input(Point lp, Token &t, Clipper *vf)
  605. {
  606.     if (t.IsKey() || t.IsFunctionKey() || t.IsCursorKey() || ContainsPoint(lp)) {
  607.     if (Enabled()) {
  608.         if (TestFlag(eVObjKbdFocus) && t.Code == eEvtLeftButton
  609.                         && !(t.Flags & eFlgButDown)) {
  610.         GetWindow()->SetFirstHandler(this);
  611.         }
  612.         return DispatchEvents(lp, t, vf);
  613.     }
  614.     return gNoChanges;
  615.     }
  616.     return 0;     
  617. }
  618.  
  619. Command *VObject::DispatchEvents(Point lp, Token &t, Clipper *vf)
  620. {
  621.     register Command *currCmd;
  622.  
  623.     if (Size() > 0) {
  624.     Iter previous(MakeIterator(FALSE));
  625.     VObject *dip;
  626.  
  627.     while (dip= (VObject*) previous()) 
  628.         if (currCmd= dip->Input(lp, t, vf))
  629.         return currCmd;
  630.     }
  631.     
  632.     currCmd= gNoChanges;
  633.     
  634.     if (t.IsMouseButton() || t.Code == eEvtLocMove || t.Code == eEvtLocStill)
  635.     GrSetCursor(GetCursor(lp));
  636.  
  637.     switch (t.Code) {
  638.     case eEvtRightButton:
  639.     if (!(t.Flags & eFlgButDown))
  640.         currCmd= DoRightButtonDownCommand(lp, t, WindowSystem::Clicks, vf);
  641.     break;
  642.     case eEvtMiddleButton:
  643.     case eEvtLeftButton:
  644.     if (!(t.Flags & eFlgButDown)) {
  645.         if (t.Code == eEvtLeftButton) {
  646.         if (t.Flags == (eFlgShiftKey|eFlgCntlKey|eFlgMetaKey))
  647.             gProgEnv->InspectClick(this);
  648.         else
  649.             currCmd= DoLeftButtonDownCommand(lp, t, WindowSystem::Clicks);
  650.         } else
  651.         currCmd= DoMiddleButtonDownCommand(lp, t, WindowSystem::Clicks);
  652.         if (currCmd && currCmd != gNoChanges && vf)
  653.         currCmd= vf->TrackInContent(lp, t, currCmd);
  654.     }
  655.     break;
  656.     default:
  657.     if (t.IsKey())
  658.         currCmd= DoKeyCommand(t.Code, t);
  659.     else if (t.IsFunctionKey()) 
  660.         currCmd= DoFunctionKeyCommand(t.FunctionCode(), t);
  661.     else if (t.IsCursorKey())
  662.         currCmd= DoCursorKeyCommand(t.CursorDir(), t);
  663.     else if (t.Code == eEvtIdle)
  664.         currCmd= DoIdleCommand();
  665.     else
  666.         currCmd= DoOtherEventCommand(lp, t);
  667.     break;
  668.     }
  669.     return currCmd;
  670. }
  671.  
  672. Command *VObject::DoKeyCommand(int ch, Token t)
  673. {
  674.     if (GetContainer())
  675.     return GetContainer()->DoKeyCommand(ch, t);
  676.     return gNoChanges;
  677. }
  678.  
  679. Command *VObject::DoCursorKeyCommand(EvtCursorDir d, Token t)
  680. {
  681.     if (GetContainer())
  682.     return GetContainer()->DoCursorKeyCommand(d, t);
  683.     return gNoChanges;
  684. }
  685.  
  686. Command *VObject::DoFunctionKeyCommand(int pfk, Token t)
  687. {
  688.     int code= -1;
  689.     
  690.     switch (t.FunctionCode()) {
  691.     case 3:
  692.     code= cUNDO;
  693.     break;
  694.     case 5:
  695.     code= cCOPY;
  696.     break;
  697.     case 4:
  698.     code= cTOP;
  699.     break;
  700.     case 7:
  701.     code= cPASTE;
  702.     break;
  703.     case 9:
  704.     code= cCUT;
  705.     break;
  706.     case 8:
  707.     code= cFIND;
  708.     break;
  709.     case 6:
  710.     code= cOPEN;
  711.     break;
  712.     }
  713.     if (code > 0)
  714.     return DoMenuCommand(code);
  715.     if (GetContainer())
  716.     return GetContainer()->DoFunctionKeyCommand(pfk, t);
  717.     return gNoChanges;
  718. }
  719.  
  720. Command *VObject::DoMiddleButtonDownCommand(Point p, Token t, int clicks)
  721. {
  722.     if (GetContainer())
  723.     return GetContainer()->DoMiddleButtonDownCommand(ContainerPoint(p), t, clicks);
  724.     return gNoChanges;
  725. }
  726.  
  727. Command *VObject::DoLeftButtonDownCommand(Point p, Token t, int clicks)
  728. {
  729.     if (GetContainer())
  730.     return GetContainer()->DoLeftButtonDownCommand(ContainerPoint(p), t, clicks);
  731.     return gNoChanges;
  732. }
  733.  
  734. Command *VObject::DoOtherEventCommand(Point p, Token t)
  735. {
  736.     if (GetContainer())
  737.     return GetContainer()->DoOtherEventCommand(ContainerPoint(p), t);
  738.     return gNoChanges;
  739. }
  740.  
  741. Command *VObject::DoRightButtonDownCommand(Point lp, Token, int, Clipper *vf)
  742. {
  743.     if (vf) {
  744.     Menu *menu= GetMenu();
  745.     if (menu) {
  746.         int cmdno;
  747.         if ((cmdno= menu->Pulldown(lp, vf)) >= 0) {     // show menu in window
  748.         vf->Focus();
  749.         if (gFirstHandler) {
  750.             EvtHandler *old= gFirstHandler;
  751.             Command *cmd= gFirstHandler->DoMenuCommand(cmdno);
  752.             gFirstHandler= old;
  753.             gFirstHandler->PerformCommand(cmd);
  754.         } else
  755.             PerformCommand(DoMenuCommand(cmdno));
  756.         
  757.         // return DoMenuCommand(cmdno);
  758.        }
  759.     }
  760.     }
  761.     return gNoChanges;
  762. }
  763.  
  764. Command *VObject::TrackInContent(Point lp, Token t, Command *currCmd)
  765. {
  766.     if (GetContainer())
  767.     return GetContainer()->TrackInContent(ContainerPoint(lp), t, currCmd);
  768.     return currCmd;
  769. }
  770.  
  771. //---- misc --------------------------------------------------------------------
  772.  
  773. void VObject::Print()
  774. {
  775.     gPrintManager->ShowPrintDialog(this);
  776. }
  777.  
  778. //---- VObjectCommand ----------------------------------------------------------
  779.  
  780. VObjectCommand::VObjectCommand(VObject *g) : Command(cIdNone)
  781. {
  782.     vop= g;
  783.     SetFlag(eCmdNoReplFeedback);
  784. }
  785.  
  786. void VObjectCommand::Init(VObject *g, Rectangle cr, Point gr, GrCursor cd, int hy)
  787. {
  788.     vop= g;
  789.     constrainRect= cr;
  790.     grid= gr;
  791.     newcursor= cd;
  792.     firstmove= FALSE;
  793.     hysterese= hy;
  794.     oldRect= newRect= vop->ContentRect();  
  795. }
  796.  
  797. Command *VObjectCommand::TrackMouse(TrackPhase atp, Point ap, Point, Point np)
  798. {
  799.     switch (atp) {
  800.     case eTrackPress:
  801.     oldcursor= GrGetCursor();
  802.     break;
  803.  
  804.     case eTrackRelease:
  805.     GrSetCursor(oldcursor);
  806.     
  807.     if (firstmove) {
  808.         if (vop->GetView() && !TestFlag(eCmdFullScreen))     
  809.         vop->SetContentRect(oldRect, FALSE);
  810.         break;
  811.     }
  812.     return gNoChanges;
  813.  
  814.     case eTrackMove:
  815.     delta= np - ap;
  816.     if (Math::Abs(delta.x) > hysterese || Math::Abs(delta.y) > hysterese) {
  817.         firstmove= TRUE;
  818.         GrSetCursor(newcursor);
  819.     }
  820.     break;
  821.     default:
  822.     break;
  823.     }
  824.     return this;
  825. }
  826.  
  827. void VObjectCommand::TrackConstrain(Point ap, Point, Point *np)
  828. {
  829.     Rectangle r= oldRect;
  830.  
  831.     r.origin+= *np-ap;
  832.     *np+= r.AmountToTranslateWithin(constrainRect);
  833.     if (grid >= 1)
  834.     *np= (*np/grid) * grid;     // align to grid
  835. }
  836.  
  837. void VObjectCommand::TrackFeedback(Point, Point, bool on)
  838. {
  839.     if (firstmove) {
  840.     if (GrGetPenInk() != ePatXor) {
  841.         if (on)
  842.         vop->SetContentRect(newRect, TRUE);
  843.     } else
  844.         vop->Outline2(newRect.NW(), newRect.SE());
  845.     }
  846. }
  847.  
  848. void VObjectCommand::DoIt()
  849. {
  850.     vop->SetContentRect(newRect, !TestFlag(eCmdFullScreen));
  851. }
  852.  
  853. void VObjectCommand::UndoIt()
  854. {
  855.     vop->SetContentRect(oldRect, !TestFlag(eCmdFullScreen));
  856. }
  857.  
  858. //---- VObjectMover ------------------------------------------------------------
  859.  
  860. VObjectMover::VObjectMover(VObject *g) : VObjectCommand(g)
  861. {
  862.     Init(g, gRect0, gPoint1, eCrsMoveHand, 2);
  863. }
  864.  
  865. VObjectMover::VObjectMover(VObject *g, Rectangle cr) : VObjectCommand(g)
  866. {
  867.     Init(g, cr, gPoint1, eCrsMoveHand, 2);
  868. }
  869.  
  870. VObjectMover::VObjectMover(VObject *g, Rectangle cr, Point gr, GrCursor cd,
  871.                             int hy) : VObjectCommand(g)
  872. {
  873.     Init(g, cr, gr, cd, hy);
  874. }
  875.  
  876. void VObjectMover::Init(VObject *g, Rectangle cr, Point gr, GrCursor cd, int hy)
  877. {
  878.     SetName("move");
  879.     VObjectCommand::Init(g, cr, gr, cd, hy);
  880. }
  881.  
  882. Command *VObjectMover::TrackMouse(TrackPhase atp, Point ap, Point pp, Point np)
  883. {
  884.     Command *cmd= VObjectCommand::TrackMouse(atp, ap, pp, np);
  885.     switch (atp) {
  886.     case eTrackMove:
  887.     newRect= oldRect;
  888.     newRect.origin+= delta;
  889.     return this;
  890.     case eTrackRelease:
  891.     if (newRect == oldRect) {
  892.         if (vop->IsKindOf(Window))
  893.         ((Window*)vop)->Top();
  894.         cmd= gNoChanges;
  895.     }
  896.     break;
  897.     default:
  898.     break;
  899.     }
  900.     return cmd;
  901. }
  902.  
  903. //---- VObjectStretcher --------------------------------------------------------
  904.  
  905. VObjectStretcher::VObjectStretcher(VObject *g) : VObjectCommand(g)
  906. {
  907.     Init(g, gRect0, gPoint1, eCrsMoveStretch, 2, g->GetMinSize());
  908. }
  909.  
  910. VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr) : VObjectCommand(g)
  911. {
  912.     Init(g, cr, gPoint1, eCrsMoveStretch, 2, g->GetMinSize());
  913. }
  914.  
  915. VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr, Point ms) : VObjectCommand(g)
  916. {
  917.     Init(g, cr, ms, eCrsMoveStretch, 2, g->GetMinSize());
  918. }
  919.  
  920. VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr, Point ms, Point gr,
  921.                     GrCursor cd, int hy) : VObjectCommand(g)
  922. {
  923.     Init(g, cr,  gr, cd, hy, ms);
  924. }
  925.  
  926. void VObjectStretcher::Init(VObject *g, Rectangle cr, Point gr,
  927.                         GrCursor cd, int hy, Point ms)
  928. {
  929.     SetName("resize");
  930.     VObjectCommand::Init(g, cr, gr, cd, hy);
  931.     minSize= ms;
  932. }
  933.  
  934. void VObjectStretcher::TrackConstrain(Point ap, Point, Point *np)
  935. {  
  936.     switch (corner) {
  937.     case 0: case 4:
  938.     np->x= ap.x;
  939.     break;
  940.     case 2: case 6:
  941.     np->y= ap.y;
  942.     break;
  943.     }
  944. }
  945.  
  946. Command *VObjectStretcher::TrackMouse(TrackPhase atp, Point ap, Point pp, Point np)
  947. {
  948.     Point p1, p2;
  949.  
  950.     switch (atp) {
  951.     case eTrackPress:
  952.     VObjectCommand::TrackMouse(atp, ap, pp, np);
  953.     corner= oldRect.PointToCorner(ap);
  954.     break;
  955.  
  956.     case eTrackMove:
  957.     VObjectCommand::TrackMouse(atp, ap, pp, np);
  958.     p1= oldRect.NW();
  959.     p2= oldRect.SE();
  960.  
  961.     switch (corner) {
  962.     case 0: case 6: case 7:
  963.         p1+= delta;
  964.         break;
  965.     case 1:
  966.         p2.x+= delta.x;
  967.         p1.y+= delta.y;
  968.         break;
  969.     case 5:
  970.         p1.x+= delta.x;
  971.         p2.y+= delta.y;
  972.         break;
  973.     default: // case 2: case 3: case 4:
  974.         p2+= delta;
  975.         break;
  976.     }
  977.     newRect= NormRect(p1, p2);
  978.     newRect.extent= Max(newRect.extent, minSize);
  979.     break;
  980.  
  981.     case eTrackRelease:
  982.     return VObjectCommand::TrackMouse(atp, ap, pp, np);
  983.  
  984.     default:
  985.     break;
  986.     }
  987.     return this;
  988. }
  989.  
  990.